home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / packer / mcvert / hqxify.c next >
C/C++ Source or Header  |  1995-08-07  |  20KB  |  584 lines

  1. #include "mactypes.h"
  2.  
  3. #define HQXBUFLEN 512
  4. byte hqxbuf[HQXBUFLEN+1], *buf_ptr, *buf_end, *buf_start=hqxbuf+1;
  5.  
  6. #define MAXLINE 255
  7. byte line[MAXLINE+1], *line_ptr, *line_end, *line_start=line+1;
  8.  
  9. int line_count, file_count;
  10. int save_state, total_bytes, save_run_length;
  11. word save_nibble;
  12. char binfname[BINNAMELEN], hqxfname[BINNAMELEN];
  13. FILE *hqxfile, *binfile;
  14.  
  15. /* This routine reads the header of a hqxed file and appropriately twiddles it,
  16.     determines if it has CRC problems, creates the .bin file, and puts the info
  17.     into the .bin file.
  18.     Output is hqx_datalen, hqx_rsrclen, type, binfname, binfile */
  19.  
  20. hqx_to_bin_hdr(type, hqx_datalen, hqx_rsrclen)
  21. char *type;
  22. ulong *hqx_datalen, *hqx_rsrclen;
  23. {   register byte *hqx_ptr, *hqx_end;
  24.     register ulong calc_crc;
  25.     hqx_buf *hqx_block;
  26.     hqx_header *hqx;
  27.     info_header info;
  28.     ulong mtim;
  29.     short crc;
  30.  
  31.     extern word magic[];
  32.     extern FILE *output;
  33.     extern char *dir, *ext;
  34.     extern short calc_mb_crc();
  35.  
  36.     /* read the hqx header, assuming that I won't exhaust hqxbuf in so doing */
  37.     fill_hqxbuf();
  38.     hqx_block = (hqx_buf *) buf_ptr;
  39.     hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  40.     hqx_ptr = buf_ptr;
  41.     hqx_end = (byte *) hqx + sizeof(hqx_header) - 1;
  42.     calc_crc = 0;
  43.     while (hqx_ptr < hqx_end)
  44.         calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  45.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  46.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  47.     buf_ptr = hqx_ptr;
  48.  
  49.     /* stuff the hqx header data into the info header */
  50.     bzero(&info, sizeof(info_header));
  51.     info.nlen = hqx_block->nlen;
  52.     strncpy(info.name, hqx_block->name, info.nlen);     /* name */
  53.     bcopy(hqx->type, info.type, 9);             /* type, author, flag */
  54.     info.flags  &= 0x7e;                        /* reset lock bit, init bit */
  55.     if (hqx->protect & 0x40) info.protect = 1;  /* copy protect bit */
  56.     bcopy(hqx->dlen, info.dlen, 8);             /* dlen, rlen */
  57.     mtim = time2mac(time(0));
  58.     bcopy(&mtim, info.mtim, 4);
  59.     bcopy(&mtim, info.ctim, 4);
  60.     info.uploadvers = '\201';
  61.     info.readvers = '\201';
  62.  
  63.     /* calculate MacBinary CRC */
  64.     crc = calc_mb_crc(&info, 124, 0);
  65.     info.crc[0] = (char) (crc >> 8);
  66.     info.crc[1] = (char) crc;
  67.  
  68.     /* Create the .bin file and write the info to it */
  69.     unixify(hqx_block->name);
  70.     sprintf(binfname, "%s/%s%s", dir, hqx_block->name, ext);
  71.     fprintf(output,
  72.         "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  73.         hqx_block->name, info.type, info.auth);
  74.     if ((binfile = fopen(binfname, "w")) == NULL)
  75.         error("Cannot open %s", binfname);
  76.     check_hqx_crc(calc_crc, "File header CRC mismatch in %s", binfname);
  77.     fwrite(&info, sizeof(info), 1, binfile);
  78.  
  79.     /* Get a couple of items we'll need later */
  80.     bcopy(info.dlen, hqx_datalen, 4);
  81.     *hqx_datalen = mac2long(*hqx_datalen);
  82.     bcopy(info.rlen, hqx_rsrclen, 4);
  83.     *hqx_rsrclen = mac2long(*hqx_rsrclen);
  84.     bcopy(info.type, type, 4);
  85.     }
  86.  
  87. /* This routine reads the header of a bin file and appropriately twiddles it,
  88.     creates the .hqx file, and puts the info into the .hqx file.
  89.     Output is hqx_datalen, hqx_rsrclen, type, hqxfname, hqxfile */
  90.  
  91. bin_to_hqx_hdr(hqx_datalen, hqx_rsrclen)
  92. ulong *hqx_datalen, *hqx_rsrclen;
  93. {   register byte *hqx_ptr, *hqx_end;
  94.     register ulong calc_crc;
  95.     hqx_buf *hqx_block;
  96.     hqx_header *hqx;
  97.     info_header info;
  98.     extern word magic[];
  99.     extern FILE *output;
  100.     extern char **hqxnames_left;
  101.     extern char *ext;
  102.  
  103.     strcpy(binfname, *hqxnames_left++);
  104.     if (!(binfile = fopen(binfname, "r"))) {
  105.         /* Maybe we are supposed to figure out the suffix ourselves? */
  106.         strcat(binfname, ext);
  107.         if (!(binfile = fopen(binfname, "r")))
  108.             error("Cannot open %s", binfname);
  109.         }
  110.     if (!fread(&info, sizeof(info), 1, binfile))
  111.         error("Unexpected EOF in header of %s", binfname);
  112.  
  113.     /* stuff the info header into the hqx header */
  114.     hqx_block = (hqx_buf *) buf_ptr;
  115.     hqx_block->nlen = info.nlen;
  116.     strncpy(hqx_block->name, info.name, info.nlen);
  117.     hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  118.     hqx->version  = 0;
  119.     bcopy(info.type, hqx->type, 9);             /* type, author, flags */
  120.     if (info.protect = 1) hqx->protect = 0;     /* protect bit: 0x40 */
  121.     else hqx->protect = 0;
  122.     bcopy(info.dlen, hqx->dlen, 8);             /* dlen, rlen */
  123.  
  124.     /* Create the .hqx file and write the info to it */
  125.     strncpy(hqxfname, info.name, info.nlen);
  126.     hqxfname[info.nlen] = '\0';
  127.     unixify(hqxfname);
  128.     fprintf(output,
  129.         "Converting     %-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  130.         hqxfname, info.type, info.auth);
  131.  
  132.     calc_crc = 0;
  133.     hqx_ptr = (byte *) hqx_block;
  134.     hqx_end = hqx_ptr + hqx_block->nlen + sizeof(hqx_header);
  135.     while (hqx_ptr < hqx_end)
  136.         calc_crc = (((calc_crc&0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  137.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  138.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  139.     buf_ptr = hqx_end;
  140.     write_hqx_crc(calc_crc);
  141.  
  142.     /* Get a couple of items we'll need later */
  143.     bcopy(info.dlen, hqx_datalen, 4);
  144.     *hqx_datalen = mac2long(*hqx_datalen);
  145.     bcopy(info.rlen, hqx_rsrclen, 4);
  146.     *hqx_rsrclen = mac2long(*hqx_rsrclen);
  147.     }
  148.  
  149.  
  150. /* This routine copies bytes from the decoded input stream to the output.  
  151.     It also pads to a multiple of 128 bytes on the output, which is part
  152.     of the .bin format */
  153. word hqx_to_bin_fork(nbytes)
  154. register ulong nbytes;
  155. {   register byte *c;
  156.     register ulong calc_crc;
  157.     register int c_length;
  158.     ulong extra_bytes;
  159.     extern word magic[];
  160.  
  161.     extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
  162.     calc_crc = 0;
  163.     for (;;) {
  164.         c = buf_ptr;
  165.         c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
  166.         nbytes -= c_length;
  167.         fwrite(c, sizeof(byte), c_length, binfile);
  168.         while (c_length--)
  169.             calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
  170.         if (!nbytes) break;
  171.         fill_hqxbuf();
  172.         }
  173.     buf_ptr = c;
  174.     while (extra_bytes--) putc(0, binfile);
  175.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  176.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  177.     return (word) calc_crc;
  178.     }
  179.  
  180. /* This routine copies bytes from the input stream to the encoded output.  
  181.     It also pads to a multiple of 128 bytes on the input, which is part
  182.     of the .bin format */
  183. word bin_to_hqx_fork(nbytes)
  184. register ulong nbytes;
  185. {   register byte *c;
  186.     register ulong calc_crc;
  187.     register int c_length;
  188.     ulong extra_bytes;
  189.     extern word magic[];
  190.  
  191.     extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
  192.     calc_crc = 0;
  193.     for (;;) {
  194.         c = buf_ptr;
  195.         c_length = (c + nbytes > buf_end) ? buf_end - c : nbytes;
  196.         nbytes -= c_length;
  197.         fread(c, sizeof(byte), c_length, binfile);
  198.         buf_ptr += c_length;
  199.         while (c_length--)
  200.             calc_crc = (((calc_crc&0xff) << 8) | *c++) ^ magic[calc_crc >> 8];
  201.         if (!nbytes) break;
  202.         empty_hqxbuf();
  203.         }
  204.     buf_ptr = c;
  205.  
  206.     fseek(binfile, extra_bytes, 1);
  207.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  208.     calc_crc = ((calc_crc&0xff) << 8) ^ magic[calc_crc >> 8];
  209.     return (word) calc_crc;
  210.     }
  211.  
  212. /* Essentials for Binhex 8to6 run length encoding */
  213. #define RUNCHAR 0x90
  214. #define MAXRUN 255
  215. #define IS_LEGAL <0x40
  216. #define ISNT_LEGAL >0x3f
  217. #define DONE 0x7F /* tr68[':'] = DONE, since Binhex terminator is ':' */
  218. #define SKIP 0x7E /* tr68['\n'|'\r'] = SKIP, i. e. end of line char.  */
  219. #define FAIL 0x7D /* character illegal in binhex file */
  220.  
  221. byte tr86[] =
  222.         "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr"; 
  223. byte tr68[] = {
  224.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  225.     FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
  226.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  227.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  228.     FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  229.     0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
  230.     0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
  231.     0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
  232.     0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
  233.     0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
  234.     0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
  235.     0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
  236.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
  237.     0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
  238.     0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
  239.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  240.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  241.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  242.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  243.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  244.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  245.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  246.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  247.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  248.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  249.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  250.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  251.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  252.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  253.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  254.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  255.     FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  256.     };
  257.  
  258. /*
  259.  *  This procedure transparently reads and decodes the hqx input.  It does run 
  260.  *  length and 6 to 8 decoding.
  261.  */
  262. #define READING 0
  263. #define SKIPPING 1
  264. #define FIND_START_COLON 2
  265.  
  266. fill_hqxbuf()
  267. {   register ulong c, nibble;
  268.     register int not_in_a_run = TRUE, state68;
  269.     register byte *fast_buf, *fast_line;
  270.     static int status = FIND_START_COLON;
  271.  
  272.     buf_ptr = fast_buf = buf_start;
  273.     fast_line = line_ptr;
  274.     state68 = save_state;
  275.     nibble = save_nibble;
  276.     if (save_run_length > 0) {
  277.         c = save_run_length;
  278.         save_run_length = 0;
  279.         goto continue_run;
  280.         }
  281.     while (fast_buf < buf_end) {
  282.         next_char:
  283.         if ((c = *fast_line++) ISNT_LEGAL) {
  284.             if (c == DONE) break;
  285.             next_line:
  286.             if (!fgets(line_start, MAXLINE, hqxfile) && !new_in_hqx_file())
  287.                 if (status == FIND_START_COLON) exit(0);
  288.         else error("Premature EOF in %s\n", hqxfname);
  289.             line_ptr = line_start;
  290.             scan_line:
  291.             fast_line = line_ptr;
  292.         while ((*fast_line = tr68[*fast_line]) IS_LEGAL) fast_line++;
  293.         c = *fast_line;
  294.             switch (status) {
  295.             case READING:
  296.                 if (c == SKIP && fast_line == line_end) break;
  297.                 if (c == DONE) {
  298.                     status = FIND_START_COLON;
  299.                     break;
  300.                     }
  301.                 status = SKIPPING;
  302.                 goto next_line;
  303.             case SKIPPING:
  304.                 if (c == SKIP && fast_line == line_end) {
  305.                     status = READING;
  306.                     break;
  307.                     }
  308.         /*  GMT, 1/9/90: Added this clause to avoid losing the last
  309.          *  line if it was preceeded by a skipped line.  */
  310.                 if (c == DONE) {
  311.                     status = FIND_START_COLON;
  312.                     break;
  313.                     }
  314.                 goto next_line;
  315.             case FIND_START_COLON:
  316.                 if (*line_start == DONE) {
  317.                     status = READING;
  318.                     line_ptr++;
  319.                     goto scan_line;
  320.                     }
  321.                 goto next_line;
  322.                 }
  323.             fast_line = line_ptr;
  324.             c = *fast_line++;
  325.             }
  326.  
  327.         /* Finally, we have the next 6 bits worth of data */
  328.         switch (state68++) {
  329.         case 0:
  330.             nibble = c;
  331.             goto next_char;
  332.         case 1:
  333.             nibble = (nibble << 6) | c;
  334.             c = nibble >> 4;
  335.             break;
  336.         case 2:
  337.             nibble = (nibble << 6) | c;
  338.             c = (nibble >> 2) & 0xff;
  339.             break;
  340.         case 3:
  341.             c = (nibble << 6) & 0xff | c;
  342.             state68 = 0;
  343.             break;
  344.             }
  345.         if (not_in_a_run)
  346.             if (c != RUNCHAR) *fast_buf++ = c;
  347.             else {not_in_a_run = FALSE; goto next_char;}
  348.         else {
  349.             if (c--) {
  350.                 not_in_a_run = buf_end - fast_buf;
  351.                 if (c > not_in_a_run) {
  352.                     save_run_length = c - not_in_a_run;
  353.                     c = not_in_a_run;
  354.                     }
  355.                 continue_run:
  356.                 not_in_a_run = fast_buf[-1];
  357.                 while (c--) *fast_buf++ = not_in_a_run;
  358.                 }
  359.             else *fast_buf++ = RUNCHAR;
  360.             not_in_a_run = TRUE;
  361.             }
  362.         }
  363.     total_bytes += fast_buf - buf_ptr;
  364.     buf_start[-1] = fast_buf[-1];
  365.     line_ptr = fast_line;
  366.     save_state = state68;
  367.     save_nibble = nibble;
  368.     }
  369.  
  370.  
  371. new_in_hqx_file()
  372. {   char *hqx_ext;
  373.     extern char **hqxnames_left;
  374.     if (*hqxnames_left[0] == '\0' || *hqxnames_left[0] == '-') return FALSE;
  375.     strcpy(hqxfname, *hqxnames_left++);
  376.     hqx_ext = hqxfname + strlen(hqxfname) - 4;
  377.     if (!strcmp(hqx_ext, ".hqx"))
  378.         if (!freopen(hqxfname, "r", hqxfile))
  379.             error("Cannot open %s\n", hqxfname);
  380.             else;
  381.     else {
  382.         if (!freopen(hqxfname, "r", hqxfile)) {
  383.             hqx_ext += 4;
  384.             strcpy(hqx_ext, ".hqx");
  385.             if (!freopen(hqxfname, "r", hqxfile)) {
  386.                 error("Cannot find %s\n", hqxfname);
  387.             }
  388.         }
  389.       }
  390.     fgets(line_start, MAXLINE, hqxfile);
  391.     return TRUE;
  392.     }
  393.  
  394. /*
  395.  *  This procedure transparently encodes and writes the hqx output.  
  396.  *  It does run length and 8 to 6 encoding.
  397.  */
  398. empty_hqxbuf()
  399. {   register ulong c, nibble, last_c;
  400.     register byte *fast_buf, *fast_line;
  401.     register int state86, dont_look_for_runs = FALSE, run_length;
  402.     extern int maxlines;
  403.  
  404.     run_length = save_run_length;
  405.     last_c = buf_start[-1];
  406.     fast_buf = buf_start;
  407.     fast_line = line_ptr;
  408.     state86 = save_state;
  409.     nibble = save_nibble;
  410.     while (fast_buf < buf_ptr) {
  411.         c = *fast_buf++;
  412.         if (dont_look_for_runs) dont_look_for_runs = FALSE;
  413.         else if (last_c == c &&  run_length < MAXRUN) {run_length++; continue;}
  414.         else {
  415.             if (run_length >1) {
  416.                 --fast_buf;
  417.                 if (run_length == 2 && last_c != RUNCHAR) c = last_c;
  418.                 else {
  419.                     c = RUNCHAR;
  420.                     *--fast_buf = run_length;
  421.                     dont_look_for_runs = TRUE;
  422.                     }
  423.                 run_length = 1;
  424.                 }
  425.             else last_c = c;
  426.             if (c == RUNCHAR && !dont_look_for_runs) {
  427.                 *--fast_buf = 0;
  428.                 dont_look_for_runs = TRUE;
  429.                 }
  430.             }
  431.  
  432.         if (fast_line == line_end) {
  433.             if (line_count++ == maxlines) new_out_hqx_file();
  434.             fputs(line_start, hqxfile);
  435.             fast_line = line_start;
  436.             }
  437.  
  438.         switch (state86++) {
  439.         case 0:
  440.             *fast_line++ = tr86[ c >> 2 ];
  441.             nibble = (c << 4) & 0x3f;
  442.             break;
  443.         case 1:
  444.             *fast_line++ = tr86[ (c >> 4) | nibble ];
  445.             nibble = (c << 2) & 0x3f;
  446.             break;
  447.         case 2:
  448.             *fast_line++ = tr86[ (c >> 6) | nibble ];
  449.             if (fast_line == line_end) {
  450.                 if (line_count++ == maxlines) new_out_hqx_file();
  451.                 fputs(line_start, hqxfile);
  452.                 fast_line = line_start;
  453.                 }
  454.             *fast_line++ = tr86[ c & 0x3f ];
  455.             state86 = 0;
  456.             break;
  457.             }
  458.         }
  459.     save_run_length = run_length;
  460.     buf_start[-1] = last_c;
  461.     buf_ptr = buf_start;
  462.     line_ptr = fast_line;
  463.     save_state = state86;
  464.     save_nibble = nibble;
  465.     }
  466.  
  467. new_out_hqx_file()
  468. {   char filename[NAMELEN + 7];
  469.     extern int maxlines;
  470.     fprintf(hqxfile, "<<< End of Part %2d >>>\n", file_count);
  471.     fclose(hqxfile);
  472.     file_count++;
  473.     if (maxlines) sprintf(filename, "%s%02d.hqx", hqxfname, file_count);
  474.     else sprintf(filename, "%s.hqx", hqxfname);
  475.     if ((hqxfile = fopen(filename, "w")) == NULL)
  476.         error("Can't create %s", filename);
  477.     if (file_count > 1)
  478.         fprintf(hqxfile, "<<< Start of Part %2d >>>\n", file_count);
  479.     else fprintf(hqxfile, "(This file must be converted with BinHex 4.0)\n\n");
  480.     line_count = 3;
  481.     }
  482.  
  483. check_hqx_crc(calc_crc, msg, name)
  484. word calc_crc;
  485. char msg[], name[];
  486. {   word read_crc;
  487.     if (buf_ptr >= buf_end) fill_hqxbuf();
  488.     read_crc = *buf_ptr++ << 8;
  489.     if (buf_ptr >= buf_end) fill_hqxbuf();
  490.     read_crc |= *buf_ptr++;
  491.     if (read_crc != calc_crc) error(msg, name);
  492.     }
  493.  
  494. write_hqx_crc(calc_crc)
  495. word calc_crc;
  496. {   if (buf_ptr == buf_end) empty_hqxbuf();
  497.     *buf_ptr++ = calc_crc >> 8;
  498.     if (buf_ptr == buf_end) empty_hqxbuf();
  499.     *buf_ptr++ = calc_crc;
  500.     }
  501.  
  502. un_hqx(unpit_flag)
  503. int unpit_flag;
  504. {   char type[4];
  505.     ulong hqx_datalen, hqx_rsrclen;
  506.     word un_pit();
  507.     int unpitting, bytes_read;
  508.     word calc_crc;
  509.     extern char **hqxnames_left;
  510.  
  511.     hqxfile = fopen("NIL:", "r");
  512.     if (hqxfile == NULL) error("no NIL");
  513.     line_end = line_start + HQXLINELEN;
  514.     buf_end = buf_start + HQXBUFLEN;
  515.     for (;;) {
  516.         total_bytes = 0;
  517.         line_ptr = line_start;
  518.         line_ptr[0] = SKIP;
  519.         save_state = 0;
  520.         save_run_length = 0;
  521.  
  522.         hqx_to_bin_hdr(type, &hqx_datalen, &hqx_rsrclen); /* binfname */
  523.  
  524.         unpitting = unpit_flag && !strcmp(type, "PIT ");
  525.         if (unpitting) {
  526.             fclose(binfile);
  527.             unlink(binfname);
  528.             bytes_read = total_bytes - (buf_end - buf_ptr);
  529.             calc_crc = un_pit();
  530.             bytes_read = total_bytes - (buf_end - buf_ptr) - bytes_read;
  531.             if (bytes_read != hqx_datalen)
  532.                 fprintf(stderr,
  533.                   "Warning - Extraneous characters ignored in %s\n", binfname);
  534.             }
  535.         else calc_crc = hqx_to_bin_fork(hqx_datalen);
  536.         check_hqx_crc(calc_crc, "File data CRC mismatch in %s", binfname);
  537.  
  538.         calc_crc = hqx_to_bin_fork(hqx_rsrclen);
  539.         check_hqx_crc(calc_crc, "File rsrc CRC mismatch in %s", binfname);
  540.  
  541.         if (!unpitting) fclose(binfile);
  542.         }
  543.     }
  544.  
  545. re_hqx()
  546. {   word calc_crc;
  547.     ulong hqx_datalen, hqx_rsrclen;
  548.     extern char **hqxnames_left;
  549.     extern int maxlines;
  550.     line_end = line_start + HQXLINELEN;
  551.     buf_end = buf_start + HQXBUFLEN;
  552.     while (*hqxnames_left[0] != '-') {
  553.         hqxfile = fopen("NIL:", "w");
  554.         if (hqxfile == NULL) error("no NIL");
  555.         line_count = maxlines;
  556.         file_count = 0;
  557.         line_ptr = line_start;
  558.         *line_ptr++ = ':';
  559.         strcpy(line_end, "\n");
  560.         buf_ptr = buf_start;
  561.         save_state = 0;
  562.         save_run_length = 1;
  563.  
  564.         bin_to_hqx_hdr(&hqx_datalen, &hqx_rsrclen);   /* calculates hqxfname */
  565.  
  566.         calc_crc = bin_to_hqx_fork(hqx_datalen);
  567.         write_hqx_crc(calc_crc);
  568.  
  569.         calc_crc = bin_to_hqx_fork(hqx_rsrclen);
  570.         write_hqx_crc(calc_crc);
  571.         *buf_ptr = !buf_ptr[-1];      /* To end a run and to get the last */
  572.         buf_ptr++;
  573.         empty_hqxbuf();                 /* stray bits, temporarily add a char */
  574.         if (save_state != 2) --line_ptr;
  575.         if (line_ptr == line_end) {
  576.             fputs(line_start, hqxfile);
  577.             line_ptr = line_start;
  578.             }
  579.         strcpy(line_ptr, ":\n");
  580.         fputs(line_start, hqxfile);
  581.         fclose(hqxfile);
  582.         }
  583.     }
  584.